﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include "GbmpUiPlatform.h"
#include "IActionDrawArcByCenterEndPtBehavior.h"

namespace gcmp
{
    class IDocument;
    class IUiView;
    class IPropertyPanelEventArgs;
    class ISnap;
    class IGraphicsElementShape;

    class GBMP_UI_PLATFORM_EXPORT DrawArcByCenterEndPtElementBehavior : public IActionDrawArcByCenterEndPtBehavior
    {
        CANNOT_COPY_OR_ASSIGN(DrawArcByCenterEndPtElementBehavior)
    public:
        DrawArcByCenterEndPtElementBehavior(IDocument* poc);
        virtual ~DrawArcByCenterEndPtElementBehavior();

        // OnInitActionCallback
        typedef std::function<bool(IUiView* pCurrentView)> OnInitActionCallback;
        template<typename T>
        static OnInitActionCallback CreateOnInitActionCallback(
            bool(T::*func)(IUiView* pCurrentView), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnInitActionCallback(OnInitActionCallback callback);

        // 定义输入对话框的标题和控件
        typedef std::function<bool(std::wstring &title, std::vector<gcmp::OwnerPtr<gcmp::IControlDefinition>>& inputItems)> DefineInputDialogCallback;
        template<typename T>
        static DefineInputDialogCallback CreateDefineInputDialogCallback(
            bool(T::*func)(std::wstring &title, std::vector<gcmp::OwnerPtr<gcmp::IControlDefinition>>& inputItems), T* object)
        {
            return std::bind(func, object, std::placeholders::_1, std::placeholders::_2);
        }
        bool SetDefineInputDialogCallback(DefineInputDialogCallback callback);

        // 响应交互输入变化
        typedef std::function<bool(gcmp::IActionInputEventArgs* pArgs)> OnActionInputEventCallback;
        template<typename T>
        static OnActionInputEventCallback CreateOnActionInputEventCallback(
            bool(T::*func)(gcmp::IActionInputEventArgs* pArgs), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnActionInputEventCallback(OnActionInputEventCallback callback);

        // 响应属性面板事件
        typedef std::function<bool(gcmp::IPropertyPanelEventArgs* pArgs)> OnPropertyPanelEventCallback;
        template<typename T>
        static OnPropertyPanelEventCallback CreateOnPropertyPanelEventCallback(
            bool(T::*func)(IPropertyPanelEventArgs* pArgs), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnPropertyPanelEventCallback(OnPropertyPanelEventCallback callback);

        // 获取圆心点
        typedef std::function<bool(IUiView* pCurrentView)> OnGetCenterPointCallback;
        template<typename T>
        static OnGetCenterPointCallback CreateOnGetCenterPointCallback(
            bool(T::*func)(IUiView* pCurrentView), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnGetCenterPointCallback(OnGetCenterPointCallback callback);

        // 获取起点
        typedef std::function<bool(IUiView* pCurrentView)> OnGetStartPointCallback;
        template<typename T>
        static OnGetStartPointCallback CreateOnGetStartPointCallback(
            bool(T::*func)(IUiView* pCurrentView), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnGetStartPointCallback(OnGetStartPointCallback callback);

        // 获取终点
        typedef std::function<bool(IUiView* pCurrentView)> OnGetEndPointCallback;
        template<typename T>
        static OnGetEndPointCallback CreateOnGetEndPointCallback(
            bool(T::*func)(IUiView* pCurrentView), T* object)
        {
            return std::bind(func, object, std::placeholders::_1);
        }
        bool SetOnGetEndPointCallback(OnGetEndPointCallback callback);

        // 绘制圆弧结束
        typedef std::function<bool(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& centerPt, const gcmp::Vector3d& startPt,
                                    const gcmp::Vector3d& endPt)> OnFinishCallback;
        template<typename T>
        static OnFinishCallback CreateOnFinishCallback(
            bool(T::*func)(IUiView* pCurrentView, const Vector3d& centerPt, const Vector3d& startPt, const Vector3d& endPt), T* object)
        {
            return std::bind(func, object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
        }
        bool SetOnFinishCallback(OnFinishCallback callback);

        // 绘制临时圆（正在指定第二点）
        typedef std::function<bool(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& centerPt, const gcmp::Vector3d& pos,
                                    OwnerPtr<IGraphicsElementShape>& opGElementShape)> OnRadiusUpdatedCallback;
        template<typename T>
        static OnRadiusUpdatedCallback CreateOnRadiusUpdatedCallback(
            bool(T::*func)(IUiView* pCurrentView, const Vector3d& centerPt, const Vector3d& pos,
                OwnerPtr<IGraphicsElementShape>& opGElementShape), T* object)
        {
            return std::bind(func, object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
        }
        bool SetOnRadiusUpdatedCallback(OnRadiusUpdatedCallback callback);

        // 绘制临时圆弧（正在指定第三点）
        typedef std::function<bool(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& centerPt, const gcmp::Vector3d& startPt,
            const gcmp::Vector3d& pos, OwnerPtr<IGraphicsElementShape>& opGElementShape)> OnArcUpdatedCallback;
        template<typename T>
        static OnArcUpdatedCallback CreateOnArcUpdatedCallback(
            bool(T::*func)(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& centerPt, const gcmp::Vector3d& startPt,
            const gcmp::Vector3d& pos, OwnerPtr<IGraphicsElementShape>& opGElementShape), T* object)
        {
            return std::bind(func, object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
                std::placeholders::_4, std::placeholders::_5);
        }
        bool SetOnArcUpdatedCallback(OnArcUpdatedCallback callback);

        // Action析构
        typedef std::function<bool()> OnDestroyActionCallback;
        template<typename T>
        static OnDestroyActionCallback CreateOnDestroyActionCallback(
            bool(T::*func)(), T* object)
        {
            return std::bind(func, object);
        }
        bool SetOnDestroyActionCallback(OnDestroyActionCallback callback);

    protected:  
        virtual bool DefinePromptMsg(std::wstring& promptMsg, const gcmp::DrawArcCenterEndStatus drs) override;
        virtual bool DefineCursorType(gcmp::CursorType& cursorType, const gcmp::DrawArcCenterEndStatus drs) override;
        virtual bool DefineInputDialog(std::wstring& title, std::vector<gcmp::OwnerPtr<gcmp::IControlDefinition>>& inputItems) override;
        virtual bool GetOffsetValue(double& offset) override;

    private:
        virtual bool OnInitAction(IUiView* pCurrentView) override final;
        virtual bool OnActionInputEvent(gcmp::IActionInputEventArgs* pArgs) override final;
        virtual bool OnPropertyPanelEvent(gcmp::IPropertyPanelEventArgs* pArgs) override final;
        virtual bool OnEnterGettingCenterPointState(IUiView* pCurrentView) override final;
        virtual bool OnEnterGettingStartPointState(IUiView* pCurrentView) override final;
        virtual bool OnEnterGettingEndPointState(IUiView* pCurrentView) override final;
        virtual bool OnDrawArcFinished(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& centerPt, const gcmp::Vector3d& startPt, const gcmp::Vector3d& endPt,
                                     const gcmp::ISnap* centerSnap, const gcmp::ISnap* startSnap, const gcmp::ISnap* endSnap) override final; 
        virtual bool OnDestroyAction() override final;
        virtual bool GetGElementShapeOnRadiusUpdated(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& centerPt, const gcmp::Vector3d& pos,
                                                const gcmp::ISnap* centerSnap, const gcmp::ISnap* posSnap, 
                                                OwnerPtr<IGraphicsElementShape>& opGElementShape) override final;
        virtual bool GetGElementShapeOnArcUpdated(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& centerPt, const gcmp::Vector3d& startPt, const gcmp::Vector3d& pos,
                                                const gcmp::ISnap* centerSnap, const gcmp::ISnap* startSnap, const gcmp::ISnap* posSnap, 
                                                OwnerPtr<IGraphicsElementShape>& opGElementShape) override final;

    protected:
        IDocument* m_pDoc;
        OnInitActionCallback m_onInitActionCallback;
        DefineInputDialogCallback m_defineInputDialogCallback;
        OnActionInputEventCallback m_onActionInputEventCallback;
        OnPropertyPanelEventCallback m_onPropertyPanelEventCallback;
        OnGetCenterPointCallback m_onGetCenterPointCallback;
        OnGetStartPointCallback m_onGetStartPointCallback;
        OnGetEndPointCallback m_onGetEndPointCallback;
        OnFinishCallback m_onFinishCallback;
        OnRadiusUpdatedCallback m_onRadiusUpdatedCallback;
        OnArcUpdatedCallback m_onArcUpdatedCallback;
        OnDestroyActionCallback m_onDestroyActionCallback;

        double m_offset;
    };
}
